package org.springblade.modules.repair.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.repair.dto.PlanCheckStatisticsQueryDTO;
import org.springblade.modules.repair.dto.PlanSimpleInfoDTO;
import org.springblade.modules.repair.entity.ElevatorPrincipalDept;
import org.springblade.modules.repair.entity.MaintainPlanContent;
import org.springblade.modules.repair.enums.MaintainPlanContentEnum;
import org.springblade.modules.repair.enums.TaskStatusEnum;
import org.springblade.modules.repair.enums.WorkOrderTypeEnum;
import org.springblade.modules.repair.mapper.MaintainPlanContentMapper;
import org.springblade.modules.repair.service.*;
import org.springblade.modules.repair.vo.plan.statistics.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zcc
 * @version 1.0
 * @date 2022/1/4 15:26
 */
@Service
public class PlanContentStatisticalServiceImpl extends BaseServiceImpl<MaintainPlanContentMapper, MaintainPlanContent> implements PlanContentStatisticalService {

	@Autowired
	private ElevatorPrincipalDeptService elevatorPrincipalDeptService;
	@Autowired
	private IMaintainPlanContentService planContentService;
	@Autowired
	private IElevatorService elevatorService;
	@Autowired
	private IBuildingService buildingService;

	@Override
	public WxPlanStatusCountVO wxPlanStatusCount(PlanCheckStatisticsQueryDTO queryDTO) {
		String[] labelArr = {"待开始任务","维修中任务","已完成任务"};
		WxPlanStatusCountVO countVO = new WxPlanStatusCountVO();
		List<WxPlanCountItemVO> itemVOS = new ArrayList<>(labelArr.length);
		List<ElevatorPrincipalDept> epdList = elevatorPrincipalDeptService.list(Wrappers.<ElevatorPrincipalDept>lambdaQuery().in(ElevatorPrincipalDept::getDeptId,queryDTO.getDeptIds()));
		if(ObjectUtil.isNotEmpty(epdList)){
			List<Long> elevatorIds = epdList.stream().map(ElevatorPrincipalDept::getElevatorId).distinct().collect(Collectors.toList());
			List<PlanSimpleInfoDTO> planSimpleInfoDTOS = planContentService.listPlanSimpleByElevatorIds(queryDTO,elevatorIds, MaintainPlanContentEnum.MAINTAIN_WX.getId());
			if(Func.isNotEmpty(planSimpleInfoDTOS)){
				planSimpleInfoDTOS = planSimpleInfoDTOS.stream().filter(e -> e.getWorkOrderType().equals(WorkOrderTypeEnum.CLIENT.getId())).collect(Collectors.toList());
			}
			if(ObjectUtil.isNotEmpty(planSimpleInfoDTOS)){
				// 工单总数
				long planTotal = planSimpleInfoDTOS.stream().count();
				countVO.setPlanTotal(planTotal);
				for (String label : labelArr) {
					WxPlanCountItemVO itemVO = new WxPlanCountItemVO(label);
					long num;
					if(label.equals(labelArr[0])){
						// 待开始
						num = planSimpleInfoDTOS.stream().filter(e -> e.getStatus().equals(TaskStatusEnum.WX_TO_START.getStatus())).count();
					}else if(label.equals(labelArr[1])){
						// 维修中
						num = planSimpleInfoDTOS.stream().filter(e -> e.getStatus().equals(TaskStatusEnum.WX_UNDER_WAY.getStatus())).count();
					}else {
						// 已完成
						num = planSimpleInfoDTOS.stream().filter(e -> e.getStatus().equals(TaskStatusEnum.WX_SIGN_FINISH.getStatus())).count();
					}
					itemVO.setNum(num);
					itemVO.setPer(BigDecimal.valueOf(num).divide(BigDecimal.valueOf(planTotal),3, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)).setScale(1,RoundingMode.HALF_UP));
					itemVOS.add(itemVO);
				}
			}
			countVO.setItemVOS(itemVOS);
		}

		return countVO;
	}

	@Override
	public WxRepetitionVO wxRepetitionCount(PlanCheckStatisticsQueryDTO queryDTO) {
//		String[] labelArr = {"重复维修梯","非重复维修梯","正常梯"};
		String[] labelArr = {"重复故障梯","非重复故障梯"};
		List<WxPlanCountItemVO> itemVOS = new ArrayList<>(labelArr.length);
		WxRepetitionVO countVO = new WxRepetitionVO();
		List<ElevatorPrincipalDept> epdList = elevatorPrincipalDeptService.listInMaintainElevator(queryDTO.getDeptIds());
		if(ObjectUtil.isNotEmpty(epdList)){
			List<Long> elevatorIds = epdList.stream().map(ElevatorPrincipalDept::getElevatorId).distinct().collect(Collectors.toList());
			// 电梯总数
			long elevatorTotal = elevatorIds.stream().distinct().count();
			countVO.setElevatorTotal(elevatorTotal);
			List<PlanSimpleInfoDTO> planSimpleInfoDTOS = planContentService.listPlanSimpleByElevatorIds(queryDTO,elevatorIds, MaintainPlanContentEnum.MAINTAIN_WX.getId());
//			if(Func.isNotEmpty(planSimpleInfoDTOS)){
//				planSimpleInfoDTOS = planSimpleInfoDTOS.stream().filter(e -> e.getWorkOrderType().equals(WorkOrderTypeEnum.CLIENT.getId())).collect(Collectors.toList());
//			}
			for (String label : labelArr) {
				WxPlanCountItemVO itemVO = new WxPlanCountItemVO(label);
				if(ObjectUtil.isNotEmpty(planSimpleInfoDTOS)){
					// 根据电梯分组
					Map<Long,List<PlanSimpleInfoDTO>> elevatorGroup = planSimpleInfoDTOS.stream().collect(Collectors.groupingBy(PlanSimpleInfoDTO::getElevatorId));
					// 工单电梯
					List<Long> faultElevatorIds = planSimpleInfoDTOS.stream().map(PlanSimpleInfoDTO::getElevatorId).distinct().collect(Collectors.toList());
					long num;
					if(label.equals(labelArr[0])){
						// 重复故障梯数
						num = elevatorGroup.entrySet().stream().filter(e -> e.getValue().size() > 1).map(Map.Entry::getKey).count();
					}else if(label.equals(labelArr[1])){
						// 非重复故障梯数
						num = elevatorGroup.entrySet().stream().filter(e -> e.getValue().size() <= 1).map(Map.Entry::getKey).count();
					}else {
						// 正常电梯数
						num = elevatorIds.stream().filter(e -> !faultElevatorIds.contains(e)).count();
					}
					itemVO.setNum(num);
					itemVO.setPer(BigDecimal.valueOf(num).divide(BigDecimal.valueOf(elevatorTotal),3, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)).setScale(1,RoundingMode.HALF_UP));
					itemVOS.add(itemVO);
				}
			}
			countVO.setItemVOS(itemVOS);
		}

		return countVO;
	}

	@Override
	public IPage<WxBuildingSimpleVO> wxBuildingElevatorRepetitionDetail(PlanCheckStatisticsQueryDTO queryDTO, IPage<WxBuildingSimpleVO> page) {

		List<ElevatorPrincipalDept> epdList = elevatorPrincipalDeptService.list(Wrappers.<ElevatorPrincipalDept>lambdaQuery().in(ElevatorPrincipalDept::getDeptId,queryDTO.getDeptIds()));
		if(ObjectUtil.isNotEmpty(epdList)) {
			List<Long> elevatorIds = epdList.stream().map(ElevatorPrincipalDept::getElevatorId).distinct().collect(Collectors.toList());
			List<WxElevatorSimpleVO> elevatorSimpleInfoVOS = planContentService.getElevatorSimpleAndWxPlan(elevatorIds,queryDTO);
			if(ObjectUtil.isNotEmpty(elevatorSimpleInfoVOS)){
				if(1 == queryDTO.getTemp()){
					elevatorSimpleInfoVOS = elevatorSimpleInfoVOS.stream().filter(e -> e.getPlanTotal() == 0).collect(Collectors.toList());
				}else if(2 == queryDTO.getTemp()){
					elevatorSimpleInfoVOS = elevatorSimpleInfoVOS.stream().filter(e -> e.getPlanTotal() > 1).collect(Collectors.toList());
				}else if (3 == queryDTO.getTemp()){
					elevatorSimpleInfoVOS = elevatorSimpleInfoVOS.stream().filter(e -> e.getPlanTotal() == 1).collect(Collectors.toList());
				}
				if(ObjectUtil.isNotEmpty(elevatorSimpleInfoVOS)){
					List<Long> buildingIds = elevatorSimpleInfoVOS.stream().map(WxElevatorSimpleVO::getBuildingId).collect(Collectors.toList());
					List<WxBuildingSimpleVO> countVOS = planContentService.selectWxRepetitionBuildingSimpleByIds(buildingIds,page);
					Map<Long,List<WxElevatorSimpleVO>> buildingGroup = elevatorSimpleInfoVOS.stream().collect(Collectors.groupingBy(WxElevatorSimpleVO::getBuildingId));
					countVOS.forEach(e -> {
						if(ObjectUtil.isNotEmpty(buildingGroup.get(e.getBuildingId()))){
							e.setElevatorTotal(buildingGroup.get(e.getBuildingId()).stream().count());
							e.setElevatorCountVOS(buildingGroup.get(e.getBuildingId()));
						}else {
							e.setElevatorCountVOS(new ArrayList<>());
							e.setElevatorTotal(0L);
						}
					});
					return page.setRecords(countVOS);
				}
			}
		}
		return page.setRecords(new ArrayList<>());
	}

	@Override
	public Map<String, Long> wxBuildingElevatorRepetitionCount(PlanCheckStatisticsQueryDTO queryDTO) {
		Map<String,Long> resultMap = new HashMap<>(2);
		resultMap.put("buildingTotal",0L);
		resultMap.put("elevatorTotal",0L);
		List<ElevatorPrincipalDept> epdList = elevatorPrincipalDeptService.list(Wrappers.<ElevatorPrincipalDept>lambdaQuery().in(ElevatorPrincipalDept::getDeptId,queryDTO.getDeptIds()));
		if(ObjectUtil.isNotEmpty(epdList)) {
			List<Long> elevatorIds = epdList.stream().map(ElevatorPrincipalDept::getElevatorId).distinct().collect(Collectors.toList());
			List<WxElevatorSimpleVO> elevatorSimpleInfoVOS = planContentService.getElevatorSimpleAndWxPlan(elevatorIds,queryDTO);
			if(ObjectUtil.isNotEmpty(elevatorSimpleInfoVOS)){
				if(1 == queryDTO.getTemp()){
					elevatorSimpleInfoVOS = elevatorSimpleInfoVOS.stream().filter(e -> e.getPlanTotal() == 0).collect(Collectors.toList());
				}else if(2 == queryDTO.getTemp()){
					elevatorSimpleInfoVOS = elevatorSimpleInfoVOS.stream().filter(e -> e.getPlanTotal() > 1).collect(Collectors.toList());
				}else if (3 == queryDTO.getTemp()){
					elevatorSimpleInfoVOS = elevatorSimpleInfoVOS.stream().filter(e -> e.getPlanTotal() == 1).collect(Collectors.toList());
				}
				if(ObjectUtil.isNotEmpty(elevatorSimpleInfoVOS)){
					resultMap.put("buildingTotal",elevatorSimpleInfoVOS.stream().map(WxElevatorSimpleVO::getBuildingId).distinct().count());
					resultMap.put("elevatorTotal",elevatorSimpleInfoVOS.stream().map(WxElevatorSimpleVO::getElevatorId).distinct().count());
				}
			}
		}
		return resultMap;
	}

	@Override
	public Map<String, Long> wxBuildingCount(PlanCheckStatisticsQueryDTO queryDTO) {
		Map<String,Long> resultMap = new HashMap<>(3);
		resultMap.put("buildingTotal",0L);
		resultMap.put("elevatorTotal",0L);
		resultMap.put("planTotal",0L);
		List<ElevatorPrincipalDept> epdList = elevatorPrincipalDeptService.list(Wrappers.<ElevatorPrincipalDept>lambdaQuery().in(ElevatorPrincipalDept::getDeptId,queryDTO.getDeptIds()));
		if(ObjectUtil.isNotEmpty(epdList)) {
			List<Long> elevatorIds = epdList.stream().map(ElevatorPrincipalDept::getElevatorId).distinct().collect(Collectors.toList());
			List<PlanSimpleInfoDTO> planSimpleInfoDTOS = planContentService.listPlanSimpleByElevatorIds(queryDTO,elevatorIds, MaintainPlanContentEnum.MAINTAIN_WX.getId());
			if(Func.isNotEmpty(planSimpleInfoDTOS)){
				planSimpleInfoDTOS = planSimpleInfoDTOS.stream().filter(e -> e.getWorkOrderType().equals(WorkOrderTypeEnum.CLIENT.getId())).collect(Collectors.toList());
			}
			if(ObjectUtil.isNotEmpty(planSimpleInfoDTOS)){
				if(0 != queryDTO.getPlanStatus()){
					planSimpleInfoDTOS = planSimpleInfoDTOS.stream().filter(e -> e.getStatus().equals(queryDTO.getPlanStatus())).collect(Collectors.toList());
				}
				if(ObjectUtil.isNotEmpty(planSimpleInfoDTOS)){
					resultMap.put("buildingTotal",planSimpleInfoDTOS.stream().map(PlanSimpleInfoDTO::getBuildingId).distinct().count());
					resultMap.put("elevatorTotal",planSimpleInfoDTOS.stream().map(PlanSimpleInfoDTO::getElevatorId).distinct().count());
					resultMap.put("planTotal",planSimpleInfoDTOS.stream().map(PlanSimpleInfoDTO::getPlanId).distinct().count());
				}
			}
		}
		return resultMap;
	}

	@Override
	public IPage<WxBuildingSimpleVO> wxBuildingDetail(PlanCheckStatisticsQueryDTO queryDTO, IPage<WxBuildingSimpleVO> page) {
		List<ElevatorPrincipalDept> epdList = elevatorPrincipalDeptService.list(Wrappers.<ElevatorPrincipalDept>lambdaQuery().in(ElevatorPrincipalDept::getDeptId,queryDTO.getDeptIds()));
		if(ObjectUtil.isNotEmpty(epdList)) {
			List<Long> elevatorIds = epdList.stream().map(ElevatorPrincipalDept::getElevatorId).distinct().collect(Collectors.toList());
			List<PlanSimpleInfoDTO> planSimpleInfoDTOS = planContentService.listPlanSimpleByElevatorIds(queryDTO,elevatorIds, MaintainPlanContentEnum.MAINTAIN_WX.getId());
			if(Func.isNotEmpty(planSimpleInfoDTOS)){
				planSimpleInfoDTOS = planSimpleInfoDTOS.stream().filter(e -> e.getWorkOrderType().equals(WorkOrderTypeEnum.CLIENT.getId())).collect(Collectors.toList());
			}
			if(ObjectUtil.isNotEmpty(planSimpleInfoDTOS)){
				if(0 != queryDTO.getPlanStatus()){
					planSimpleInfoDTOS = planSimpleInfoDTOS.stream().filter(e -> e.getStatus().equals(queryDTO.getPlanStatus())).collect(Collectors.toList());
				}
				if(ObjectUtil.isNotEmpty(planSimpleInfoDTOS)){
					List<Long> buildingIds = planSimpleInfoDTOS.stream().map(PlanSimpleInfoDTO::getBuildingId).collect(Collectors.toList());
					List<WxBuildingSimpleVO> countVOS = planContentService.selectWxRepetitionBuildingSimpleByIds(buildingIds,page);
					Map<Long,List<PlanSimpleInfoDTO>> buildingGroup = planSimpleInfoDTOS.stream().collect(Collectors.groupingBy(PlanSimpleInfoDTO::getBuildingId));
					countVOS.forEach(e -> {
						if(ObjectUtil.isNotEmpty(buildingGroup.get(e.getBuildingId()))){
							e.setElevatorTotal(buildingGroup.get(e.getBuildingId()).stream().count());
							List<PlanSimpleInfoDTO> buildingPlan = buildingGroup.get(e.getBuildingId());
							buildingPlan.sort(Comparator.comparing(PlanSimpleInfoDTO::getPlanDate));
							buildingPlan.forEach(j -> j.setStatusDesc(TaskStatusEnum.getTaskName(j.getTypeStatus(),j.getStatus())));
							e.setPlanSimpleInfoDTOS(buildingPlan);
						}else {
							e.setPlanSimpleInfoDTOS(new ArrayList<>());
							e.setElevatorTotal(0L);
						}
					});
					return page.setRecords(countVOS);
				}
			}
		}
		return page.setRecords(new ArrayList<>());
	}

}
